﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Repo7.BusinessLogic.Network;
using System.Configuration;
using Repo7.BusinessLogic.Utils.Exceptions;
using Repo7.BusinessLogic.Network.Cluster;
using System.Xml.Linq;

namespace Repo7.BusinessLogic.Utils
{
    /// <summary>
    /// Commonly used methods
    /// </summary>
    public class CommonUtils
    {
        #region Constants

        public const string ConfigurationFileName = "repo7.config.xml";

        #endregion

        #region Application Configuration

        /// <summary>
        /// Repo7 Configuration Section Name
        /// </summary>
        public const string Repo7ConfigurationSectionName = "Repo7";

        /// <summary>
        /// Get the configured Peer Endpoints
        /// </summary>
        /// <returns></returns>
        public static IList<RepoPeerInfo> GetConfiguredRepositoryPeers()
        {
            IList<RepoPeerInfo> peersList = new List<RepoPeerInfo>();

            Repo7Configurations configurations = (Repo7Configurations)ConfigurationManager.GetSection(CommonUtils.Repo7ConfigurationSectionName);
            if (configurations.Peers != null || configurations.Peers.Count == 0)
            {
                foreach (var peer in configurations.Peers)
                {
                    RepoPeerInfo peerInfo = new RepoPeerInfo((peer as Repo7Peer).Name);
                    bool isCommandEndPointSet = peerInfo.TrySetCommandEndPoint((peer as Repo7Peer).CommandEndPoint);
                    bool isFileTransferEndPointSet = peerInfo.TrySetFileTransferEndPoint((peer as Repo7Peer).FileTransferEndPoint);

                    if (isCommandEndPointSet && isFileTransferEndPointSet)
                    {
                        peersList.Add(peerInfo);
                    }
                }
            }

            return peersList;
        }

        /// <summary>
        /// Get the local repository configuration
        /// </summary>
        /// <returns>RepoPeerInfo</returns>
        public static RepoLocalInfo GetLocalRepositoryConfiguration()
        {
            Repo7Configurations configurations = (Repo7Configurations)ConfigurationManager.GetSection(CommonUtils.Repo7ConfigurationSectionName);
            RepoLocalInfo localInfo = new RepoLocalInfo(configurations.Local.RepoDirectoryPath);
            bool isCommandEndPointSet = localInfo.TrySetCommandEndPoint(configurations.Local.CommandEndPoint);
            bool isFileTransferEndPointSet = localInfo.TrySetFileTransferEndPoint(configurations.Local.FileTransferEndPoint);

            if (isCommandEndPointSet && isFileTransferEndPointSet)
            {
                return localInfo;
            }
            else
            {
                throw new Repo7Exception(Messages.LocalConfigurationIsInvalid);
            }
        }



        #endregion

        #region Reading External Xml Configurations

        /// <summary>
        /// Get the configured repository peers
        /// </summary>
        /// <returns></returns>
        public static IList<RepoPeerInfo> GetXmlConfiguredRepositoryPeers()
        {
            IList<RepoPeerInfo> peerInfo = new List<RepoPeerInfo>();
            XDocument xDoc = XDocument.Load(CommonUtils.ConfigurationFileName);
            XElement root = xDoc.Element("Repo7");

            var peerElements = root.Element("Repo7Peers").Elements("Peer");
            foreach (var x in peerElements)
            {
                RepoPeerInfo peer = new RepoPeerInfo(x.Attribute("name").Value);
                bool isCommandEndPointSet = peer.TrySetCommandEndPoint(x.Attribute("commandEndPoint").Value);
                bool isFileTransferEndPointSet = peer.TrySetFileTransferEndPoint(x.Attribute("fileTransferEndPoint").Value);
                peer.IsMaster = bool.Parse(x.Attribute("isMaster").Value);

                if (isCommandEndPointSet && isFileTransferEndPointSet)
                {
                    peerInfo.Add(peer);
                }
                else
                {
                    throw new Repo7Exception(Messages.LocalConfigurationIsInvalid);
                }
            }

            return peerInfo;
        }

        /// <summary>
        /// Get configured local node
        /// </summary>
        /// <returns></returns>
        public static RepoLocalInfo GetXmlLocalRepositoryConfiguration()
        {
            XDocument xDoc = XDocument.Load(CommonUtils.ConfigurationFileName);
            XElement root = xDoc.Element("Repo7");
            var localElement = root.Element("Repo7Local");

            RepoLocalInfo localInfo = new RepoLocalInfo(localElement.Attribute("repoDirectoryPath").Value);
            bool isCommandEndPointSet = localInfo.TrySetCommandEndPoint(localElement.Attribute("commandEndPoint").Value);
            bool isFileTransferEndPointSet = localInfo.TrySetFileTransferEndPoint(localElement.Attribute("fileTransferEndPoint").Value);
            localInfo.IsMaster = bool.Parse(localElement.Attribute("isMaster").Value);

            if (isCommandEndPointSet && isFileTransferEndPointSet)
            {
                return localInfo;
            }
            else
            {
                throw new Repo7Exception(Messages.LocalConfigurationIsInvalid);
            }

        }

        #endregion
    }
}
